package com.xbongbong.paas.service.workflow;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.executor.command.FormDataUpdateServiceFactory;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.feign.WorkOrderV2WorkflowFeignClient;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.FormDataHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.dto.FormDataUpdateDTO;
import com.xbongbong.paas.pojo.vo.FormDataUpdateVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.interfaces.FormDataUpdateService;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.vo.BeforeUpdateVO;
import com.xbongbong.pro.formdata.pojo.vo.UpdateVO;
import com.xbongbong.saas.constant.StockConstant;
import com.xbongbong.saas.domain.entity.WorkOrderEntity;
import com.xbongbong.saas.domain.entity.WorkOrderFormEntity;
import com.xbongbong.saas.domain.entity.ext.WorkOrderExplainEntityExt;
import com.xbongbong.saas.enums.InstockTypeEnum;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.saas.model.WorkOrderModel;
import com.xbongbong.util.OwnerIdAndCoUserIdUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 吴峰
 * @date 2021/07/20 10:39
 */
@Service("workflowDataServiceImpl")
public class WorkflowDataServiceImpl implements WorkflowDataService {

    private static final Logger LOGGER = LoggerFactory.getLogger(WorkflowDataServiceImpl.class);

    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private FormDataHelp formDataHelp;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private FormDataUpdateServiceFactory formDataUpdateServiceFactory;
    @Resource
    private WorkOrderModel workOrderModel;
    @Resource
    private WorkOrderV2WorkflowFeignClient workOrderV2WorkflowFeignClient;

    @Override
    public FormDataUpdateVO update(FormDataUpdateDTO formDataUpdateDTO) throws XbbException {
        try {
            Integer businessType = formDataUpdateDTO.getBusinessType();
            if (XbbRefTypeEnum.workOrderV2SupportApproval().contains(businessType)) {
                // 工单新项目需要调整到工单执行
                return updateWorkOrderV2Business(formDataUpdateDTO);
            }
            Integer saasMark = formDataUpdateDTO.getSaasMark();
            Long formId = formDataUpdateDTO.getFormId();
            String corpid = formDataUpdateDTO.getCorpid();
            BeforeUpdateVO beforeSaveVO = new BeforeUpdateVO();
            PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
            if ( Objects.equals(formDataUpdateDTO.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode()) ) {
                WorkOrderExplainEntityExt workOrderExplainEntityExt = workOrderExplainModel.getByFormId(formId, corpid);
                BeanUtil.copyProperties(workOrderExplainEntityExt, paasFormExplainEntity);
            } else if ( Objects.equals(businessType, XbbRefTypeEnum.PAY_SHEET.getCode()) || Objects.equals(businessType, XbbRefTypeEnum.PAYMENT_SHEET.getCode()) ) {
                paasFormExplainEntity = paasFormExplainModel.getByBusinessType(businessType, corpid);
            } else {
                paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
            }
            List<FieldAttrEntity> fieldList = JSON.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMapByList(fieldList);
            beforeSaveVO.setSaasNeedRedundantAttrPojo(formDataUpdateDTO.getSaasNeedRedundantAttrPoJo());
            beforeSaveVO.setExplainMap(explainMap);
            formDataUpdateDTO.setExplainMap(explainMap);
            beforeSaveVO.setExplainList(fieldList);
            JSONObject data = formDataUpdateDTO.getDataList();
            FormDataUpdateVO formDataSaveVO;
            if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), businessType)) {
                WorkOrderEntity oldWorkOrderEntity = workOrderModel.getByKey(formDataUpdateDTO.getDataId(), corpid);
                WorkOrderEntity workOrderEntity = new WorkOrderEntity();
                BeanUtil.copyProperties(oldWorkOrderEntity, workOrderEntity);
                workOrderEntity.setId(formDataUpdateDTO.getDataId());
                workOrderEntity.setCorpid(corpid);
                workOrderEntity.setSerialNo(data.getString(FieldTypeEnum.SERIALNO.getAlias()));
                workOrderEntity.setOwnerId(data.getString(FieldTypeEnum.OWNERID.getAlias()));
                workOrderEntity.setDepartmentId(data.getLong(FieldTypeEnum.DEPARTMENTID.getAlias()));
                workOrderEntity.setFormId(formId);
                workOrderEntity.setData(data);
                WorkOrderFormEntity workOrderFormEntity = workOrderFormModel.getByKey(formId, corpid);
                beforeSaveVO.setWorkOrderEntity(workOrderEntity);
                beforeSaveVO.setOldWorkOrderEntity(oldWorkOrderEntity);
                beforeSaveVO.setNoApprovalRequired(1);
                beforeSaveVO.setWorkOrderFormEntity(workOrderFormEntity);
                FormDataUpdateService abstractFormDataUpdateService = formDataUpdateServiceFactory.getFormDataUpdateService(businessType, saasMark);
                UpdateVO updateVO = abstractFormDataUpdateService.updateForWorkflow(formDataUpdateDTO, beforeSaveVO, workOrderFormEntity, workOrderEntity, oldWorkOrderEntity);
                formDataSaveVO = abstractFormDataUpdateService.afterSaveForWorkflow(formDataUpdateDTO, beforeSaveVO, updateVO, workOrderFormEntity, workOrderEntity, oldWorkOrderEntity);
                formDataSaveVO.setFormDataId(updateVO.getDataId());
            } else {
                OwnerIdAndCoUserIdUtil.setOwnIdAndCoUserId(data, null, formDataUpdateDTO);
                PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(formId, corpid);
                if ( paasFormEntityExt == null ) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
                }
                PaasFormDataEntity oldPaasFormDataEntity = formDataHelp.getFormDataEntity(corpid, saasMark, businessType, formDataUpdateDTO.getDataId());
                PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
                if (StockConstant.OTHER_STOCK_TYPE_LIST.contains(businessType)) {
                    Integer stockBusinessType = null;
                    if (Objects.equals(businessType, XbbRefTypeEnum.OTHER_INSTOCK.getCode())) {
                        Integer type = data.getInteger(InstockEnum.TYPE.getAttr());
                        InstockTypeEnum instockTypeEnum = InstockTypeEnum.getByCode(type);
                        stockBusinessType = instockTypeEnum.getStockBusinessType();
                    } else if (Objects.equals(businessType, XbbRefTypeEnum.OTHER_OUTSTOCK.getCode())) {
                        Integer type =data.getInteger(OutstockEnum.TYPE.getAttr());
                        OutstockTypeEnum outstockTypeEnum = OutstockTypeEnum.getByCode(type);
                        stockBusinessType = outstockTypeEnum.getStockBusinessType();
                    }
                    PaasFormEntityExt realStockFormEntity = paasFormModel.getByBusinessType(stockBusinessType, corpid);
                    if (Objects.isNull(realStockFormEntity)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
                    }

                    formDataUpdateDTO.setAppId(realStockFormEntity.getAppId());
                    formDataUpdateDTO.setMenuId(realStockFormEntity.getMenuId());
                    formDataUpdateDTO.setFormId(realStockFormEntity.getId());
                    formDataUpdateDTO.setBusinessType(realStockFormEntity.getBusinessType());
                    formDataUpdateDTO.setSubBusinessType(realStockFormEntity.getBusinessType());

                    paasFormDataEntity.setAppId(realStockFormEntity.getAppId());
                    paasFormDataEntity.setMenuId(realStockFormEntity.getMenuId());
                    paasFormDataEntity.setFormId(realStockFormEntity.getId());
                    oldPaasFormDataEntity.setAppId(realStockFormEntity.getAppId());
                    oldPaasFormDataEntity.setMenuId(realStockFormEntity.getMenuId());
                    oldPaasFormDataEntity.setFormId(realStockFormEntity.getId());
                    paasFormEntityExt = realStockFormEntity;
                }
                paasFormDataEntity.setId(formDataUpdateDTO.getDataId());
                paasFormDataEntity.setCorpid(corpid);
                paasFormDataEntity.setSerialNo(data.getString(FieldTypeEnum.SERIALNO.getAlias()));
                String ownerId = oldPaasFormDataEntity.getOwnerId();
                if (data.get(FieldTypeEnum.OWNERID.getAlias()) instanceof List && !data.getJSONArray(FieldTypeEnum.OWNERID.getAlias()).isEmpty()) {
                    ownerId = data.getJSONArray(FieldTypeEnum.OWNERID.getAlias()).getString(0);
                }
                paasFormDataEntity.setOwnerId(ownerId);
                paasFormDataEntity.setDepartmentId(data.getLong(FieldTypeEnum.DEPARTMENTID.getAlias()));
                paasFormDataEntity.setData(data);
                paasFormDataEntity.setFormId(paasFormEntityExt.getId());
                beforeSaveVO.setPaasFormDataEntity(paasFormDataEntity);
                beforeSaveVO.setOldPaasFormData(oldPaasFormDataEntity);
                beforeSaveVO.setPaasFormEntityExt(paasFormEntityExt);
                beforeSaveVO.setSaasNeedRedundantAttrPojo(formDataUpdateDTO.getSaasNeedRedundantAttrPoJo());
                beforeSaveVO.setExplainMap(explainMap);
                formDataUpdateDTO.setExplainMap(explainMap);
                beforeSaveVO.setExplainList(fieldList);
                beforeSaveVO.setNoApprovalRequired(1);
                FormDataUpdateService abstractFormDataUpdateService = formDataUpdateServiceFactory.getFormDataUpdateService(businessType, saasMark);
                UpdateVO updateVO = abstractFormDataUpdateService.updateForWorkflow(formDataUpdateDTO, beforeSaveVO, paasFormEntityExt, paasFormDataEntity, oldPaasFormDataEntity);
                formDataSaveVO = abstractFormDataUpdateService.afterSaveForWorkflow(formDataUpdateDTO, beforeSaveVO, updateVO, paasFormEntityExt, paasFormDataEntity, oldPaasFormDataEntity);
                formDataSaveVO.setFormDataId(updateVO.getDataId());
            }


            return formDataSaveVO;
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("WorkflowDataServiceImpl.update error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    private FormDataUpdateVO updateWorkOrderV2Business(FormDataUpdateDTO formDataUpdateDTO) throws XbbException {
        XbbResponse<FormDataUpdateVO> xbbResponse = workOrderV2WorkflowFeignClient.update(formDataUpdateDTO, LocaleContextHolder.getLocale().toString());
        if (!xbbResponse.isSuccess()) {
            throw new XbbException(xbbResponse.getCode(), xbbResponse.getMsg());
        }
        return xbbResponse.getResult();
    }
}
